package pl.enigmatic.validation.util;

import pl.enigmatic.validation.HasValue;
import pl.enigmatic.validation.HasValueValidator;
import pl.enigmatic.validation.SimpleValidator;
import pl.enigmatic.validation.Validator;


public enum Util {
	;

	public static final <T> Validator create(final HasValue<T> valued, final SimpleValidator<T> validator) {
		return new HasValueValidator.Impl<T>(valued, validator);
	}

	public static final <T> SimpleValidator<T> AND(final SimpleValidator<T>... factors) {
		return new SimpleValidator<T>() {

			@Override
			public boolean isValueValid(final T val) {
				for (final SimpleValidator<T> f : factors) {
					if (!f.isValueValid(val)) { return false; }
				}
				return true;
			}
		};
	}

	public static final <T> SimpleValidator<T> OR(final SimpleValidator<T>... components) {
		return new SimpleValidator<T>() {

			@Override
			public boolean isValueValid(final T val) {
				for (final SimpleValidator<T> c : components) {
					if (c.isValueValid(val)) { return true; }
				}
				return false;
			}
		};
	}

	public static final <T> SimpleValidator<T> NOT(final SimpleValidator<T> validator) {
		return new SimpleValidator<T>() {

			@Override
			public boolean isValueValid(final T val) {
				return !validator.isValueValid(val);
			}
		};
	}

	public static final <T> SimpleValidator<T> XOR(final SimpleValidator<T>... factors) {
		return new SimpleValidator<T>() {

			@Override
			public boolean isValueValid(final T val) {
				boolean valid = false;
				for (final SimpleValidator<T> f : factors) {
					final boolean fval = f.isValueValid(val);
					if (fval && !valid) {
						valid = true;
					} else if (fval && valid) { return false; }
				}
				return valid;
			}
		};
	}
}